#include "Pthread_Set.h"

//************************************
// Method:    	CPU_Core_Get				绑定CPU核情况获取
// Programmer:  lww
// Time:		2019/6/9
// Returns:   	int							-1——获取失败；其他为绑定的核的编号
// Parameter: 	pthread_t thread_id			线程号
//************************************
int CPU_Core_Get(pthread_t thread_id)
{
	cpu_set_t cpu_info;
	int core_num = -1;
	int i;

	if (pthread_getaffinity_np(thread_id, sizeof(cpu_info), &cpu_info) >= 0)
	{
		for (i = 0; i < CPU_COREANY; i++)
		{
			if (CPU_ISSET(i, &cpu_info))
			{
				core_num = i;
				break;
			}
		}
	}
	return core_num;
}

//************************************
// Method:    	CPU_Core_Set					绑定指定CPU核
// Programmer:  lww
// Time:		2019/6/9
// Returns:   	bool
// Parameter: 	pthread_attr_t * thread_attr	线程属性设置结构体指针
// Parameter: 	CPU_Core_Num_e CPU_Core			需要绑定的CPU核
// Parameter: 	const char * name				线程名称
//************************************
bool CPU_Core_Set(pthread_attr_t* thread_attr, CPU_Core_Num_e CPU_Core, const char* name)
{
	cpu_set_t cpu_info;
	//< 设置与CPU核的绑定情况
	if (CPU_Core != CPU_COREANY)
	{
		CPU_ZERO(&cpu_info);
		CPU_SET(CPU_Core, &cpu_info);
		if (0 != pthread_attr_setaffinity_np(thread_attr, sizeof(cpu_set_t), &cpu_info))
		{
			pthread_attr_destroy(thread_attr);
			printf("Set affinity failed in %s\r\n", name);
			return false;
		}
	}
	printf("Set affinity is %d in %s\r\n", CPU_Core, name);
	return true;
}

//************************************
// Method:    	Thread_Property_Set				线程属性设置函数
// Programmer:  lww
// Time:		2018/11/21
// Returns:   	bool							true——设置成功；false——设置失败
// Parameter: 	char * name						线程名称
// Parameter: 	size_t * attr_size				线程栈大小（设置为NULL时将采用默认大小）
// Parameter: 	int policy						线程调度方案（SCHED_RR、SCHED_FIFO两种为实时调度方案，RR为时间片轮转方式，FIFO为先进先出调度策略）
// Parameter: 	int priority					线程优先级（1~99），数字越大优先级越高
// Parameter: 	bool detach_status				线程分离状态   true——分离；false——不分离
// Parameter: 	pthread_attr_t * thread_attr	线程属性结构体指针
//************************************
bool Thread_Property_Set(const char* name, size_t* attr_size, int policy, int priority, bool detach_status, pthread_attr_t* thread_attr, CPU_Core_Num_e CPU_Core)
{
	struct sched_param thread_param;
	int min_priority, max_priority;
	cpu_set_t cpu_info;

	pthread_attr_init(thread_attr);//< 初始化线程属性对象

	//< 设置当前线程不继承创建线程的调度策略和优先级
	if (pthread_attr_setinheritsched(thread_attr, PTHREAD_EXPLICIT_SCHED) != 0)
	{
		pthread_attr_destroy(thread_attr);
		printf("Unable to set inher in %s\r\n", name);
		return false;
	}

	//< 设置调度方式
	if (pthread_attr_setschedpolicy(thread_attr, policy) != 0)
	{
		pthread_attr_destroy(thread_attr);
		printf("Unable to set SCHED policy in %s\r\n", name);
		return false;
	}

	//< 获取最小优先级
	min_priority = sched_get_priority_min(policy);
	if (min_priority == -1)
	{
		pthread_attr_destroy(thread_attr);
		printf("Get SCHED min priority in %s\r\n", name);
		return false;
	}

	//< 获取最大优先级
	max_priority = sched_get_priority_max(policy);
	if (max_priority == -1)
	{
		pthread_attr_destroy(thread_attr);
		printf("Get SCHED max priority in %s\r\n", name);
		return false;
	}

	if (priority > max_priority || priority < min_priority)
	{
		pthread_attr_destroy(thread_attr);
		printf("Priority range is %d to %d: using %d is above or below the range in %s\r\n", min_priority, max_priority, priority, name);
		return false;
	}

	//< 设置线程优先级
	thread_param.sched_priority = priority;
	printf("Priority Setting is %d in %s\r\n", priority, name);
	if (pthread_attr_setschedparam(thread_attr, &thread_param) != 0)
	{
		pthread_attr_destroy(thread_attr);
		printf("Set priority wrong in %s\r\n", name);
		return false;
	}

	//< 设置线程分离状态
	if (detach_status == true)
		pthread_attr_setdetachstate(thread_attr, PTHREAD_CREATE_DETACHED);
	else
		pthread_attr_setdetachstate(thread_attr, PTHREAD_CREATE_JOINABLE);

	//< 设置堆栈大小
	if (attr_size != NULL)
		pthread_attr_setstacksize(thread_attr, *attr_size);


	//< duan20200609添加
	//< pthread_attr_setscope(thread_attr, PTHREAD_SCOPE_SYSTEM);


	if (false == CPU_Core_Set(thread_attr, CPU_Core, name))
		return false;
	
	return true;
}


//************************************
// Method:    	Thread_Create			创建新线程
// Programmer:  lww
// Time:		2018/9/21
// Returns:   	bool					true——创建成功；false——创建失败
// Parameter: 	char * name				线程名称
// Parameter: 	pthread_t thread_id		线程句柄
// Parameter: 	size_t* attr_size		线程栈大小（设置为NULL时将采用默认大小）
// Parameter: 	int policy				线程调度方案（SCHED_RR、SCHED_FIFO两种为实时调度方案，RR为时间片轮转方式，FIFO为先进先出调度策略）
// Parameter: 	int priority			线程优先级（1~99），数字越大优先级越高
// Parameter: 	bool detach_status		线程分离状态   true——分离；false——不分离
// Parameter: 	* work_func				线程入口函数
// Parameter: 	void * arg				线程入口函数参数
//************************************
bool Thread_Create(const char* name, pthread_t* thread_id, size_t* attr_size, int policy, int priority, bool detach_status, void *(*work_func) (void *), CPU_Core_Num_e CPU_Core, void* arg)
{
	pthread_attr_t thread_attr;

	//< 设置线程属性
	if (false == Thread_Property_Set(name, attr_size, policy, priority, detach_status, &thread_attr, CPU_Core))
	{
		return false;
	}

	//< 创建线程
	if (pthread_create(thread_id, &thread_attr, work_func, arg))
	{
		perror("pthread_create wrong\r\n");
	}
	

	printf("The affinity is %d of %s\r\n", CPU_Core_Get(*thread_id), name);

	//pid_t pid = syscall(SYS_gettid);														//获取内核中的线程ID
	//printf("the PROCESS_ID is %d\r\n", getpid());
	//printf("the KERNEL_%s is %d\r\n", name, pid);
	//printf("the USER1_%s is %lu\r\n", name, *thread_id);									//< duan20200609 添加
	//printf("the USER2_%s is %lu\r\n", name, pthread_self());

	return true;
}
